﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Think.Problems;

namespace Think.Test.Problems
{
    [TestClass]
    public class FoundationTest
    {
        [TestMethod]
        public void ConstructFoundation()
        {
            // Execute
            var foundation = new Foundation(CardSuit.Club);

            // Assert
            Assert.AreEqual(CardSuit.Club, foundation.Suit);
        }

        [TestMethod]
        public void SetAThruKOnTheFoundation()
        {
            // Setup
            var foundation = new Foundation(CardSuit.Club);
            
            // Execute
            foundation.Set("AC");
            foundation.Set("2C");
            foundation.Set("3C");
            foundation.Set("4C");
            foundation.Set("5C");
            foundation.Set("6C");
            foundation.Set("7C");
            foundation.Set("8C");
            foundation.Set("9C");
            foundation.Set("10C");
            foundation.Set("JC");
            foundation.Set("QC");
            foundation.Set("KC");

            // Assert
            Assert.AreEqual(13, foundation.Value);
        }

        [TestMethod]
        public void CallCanSetWithValidNextCard()
        {
            // Setup
            var foundation = new Foundation(CardSuit.Club);
            foundation.Set("AC");
            foundation.Set("2C");
            foundation.Set("3C");

            // Execute
            var result = foundation.CanSet("4C");

            // Assert
            Assert.IsTrue(result);
        }

        [TestMethod]
        public void CallCanSetWithWrongSuit()
        {
            // Setup
            var foundation = new Foundation(CardSuit.Club);
            foundation.Set("AC");
            foundation.Set("2C");
            foundation.Set("3C");

            // Execute
            var result = foundation.CanSet("4H");
            
            // Assert
            Assert.IsFalse(result);
        }

        [TestMethod]
        public void CallCanSetThatIsNotNext()
        {
            // Setup
            var foundation = new Foundation(CardSuit.Club);
            foundation.Set("AC");
            foundation.Set("2C");
            foundation.Set("3C");

            // Execute
            var result = foundation.CanSet("8C");

            // Assert
            Assert.IsFalse(result);
        }

        [TestMethod]
        [ExpectedException(typeof(ArgumentNullException))]
        public void CallCanSetNullCard()
        {
            // Setup
            var foundation = new Foundation(CardSuit.Club);
            
            // Execute
            var result = foundation.CanSet(null);

            // Assert
            Assert.IsFalse(result);
        }

        [TestMethod]
        public void SetWithValidNextCard()
        {
            // Setup
            var foundation = new Foundation(CardSuit.Club);
            foundation.Set("AC");
            foundation.Set("2C");
            foundation.Set("3C");

            // Execute
            foundation.Set("4C");

            // Assert
            Assert.AreEqual(4, foundation.Value);
        }

        [TestMethod]
        [ExpectedException(typeof(InvalidOperationException))]
        public void SetCardOfWrongSuit()
        {
            // Setup
            var foundation = new Foundation(CardSuit.Club);
            foundation.Set("AC");
            foundation.Set("2C");
            foundation.Set("3C");

            // Execute
            foundation.Set("4H");
        }

        [TestMethod]
        [ExpectedException(typeof(InvalidOperationException))]
        public void SetCardThatIsNotNext()
        {
            // Setup
            var foundation = new Foundation(CardSuit.Club);
            foundation.Set("AC");
            foundation.Set("2C");
            foundation.Set("3C");

            // Execute
            foundation.Set("8C");
        }

        [TestMethod]
        [ExpectedException(typeof(ArgumentNullException))]
        public void SetNullCard()
        {
            // Setup
            var foundation = new Foundation(CardSuit.Club);

            // Execute
            foundation.Set(null);
        }

        [TestMethod]
        public void CheckWhetherFoundationIsComplete()
        {
            // Setup
            var foundation = new Foundation(CardSuit.Heart);

            // Execute
            foreach (var card in Card.Cards(foundation.Suit).OrderBy(Card.RankValue))
                foundation.Set(card);

            // Assert
            Assert.IsTrue(foundation.IsComplete);
        }

        [TestMethod]
        public void CheckWhetherIncompleteFoundationIsComplete()
        {
            // Setup
            var foundation = new Foundation(CardSuit.Diamond);

            // Execute
            foundation.Set("AD");
            foundation.Set("2D");

            // Assert
            Assert.AreEqual("2D", foundation.TopCard);
        }

        [TestMethod]
        public void CloneFoundation()
        {
            // Setup
            var foundation = new Foundation(CardSuit.Club);
            foundation.Set("AC");
            foundation.Set("2C");
            foundation.Set("3C");

            // Execute
            Foundation result = foundation.Clone();

            // Assert
            Assert.AreEqual(foundation.Suit, result.Suit);
            Assert.AreEqual(foundation.Value, result.Value);
        }
    }
}
